﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace GoodroommateComputingPlatform.Tasks
{

#if false
    public class TaskManager : ITaskManager
    {
        private class TaskS
        {
            public TaskDelegate Action { get; set; }
            public object Globls { get; set; }
            public bool Busy { get; set; }
        }
        
        private Dictionary<string, TaskS> tasks = new Dictionary<string, TaskS>();

        public void RegisterTask(string name, TaskDelegate action, object globals)
        {
            lock (tasks)
            {
                if (tasks.ContainsKey(name))
                    throw new InvalidOperationException();
                TaskS task = new TaskS()
                {
                    Action = action,
                    Globls = globals
                };
                tasks.Add(name, task);
            }
        }

        public bool IsBusy(string name)
        {
            if (!tasks.ContainsKey(name))
                throw new ArgumentException(nameof(name));
            return tasks[name].Busy;
        }

        public void StartTaskIfIdle(string name, object state, TaskCallback callback)
        {
            TaskS task = null;
            lock (tasks)
            {
                if (!tasks.ContainsKey(name))
                    throw new ArgumentException(nameof(name));
                task = tasks[name];
                if (task.Busy)
                    return;
                task.Busy = true;
            }
            Action<TaskDetail> wrapper = TaskWrapper;
            TaskDetail detail = new TaskDetail()
            {
                Name = name,
                Wrapper = wrapper,
                Action = task.Action,
                Globls = task.Globls,
                State = state,
                Callback = callback
            };
            wrapper.BeginInvoke(detail, TaskCallback, detail);
        }
        public void StartTask(string name, object state, TaskCallback callback)
        {
            TaskS task = null;
            lock (tasks)
            {
                if (!tasks.ContainsKey(name))
                    throw new ArgumentException(nameof(name));
                task = tasks[name];
                if (task.Busy)
                    throw new InvalidOperationException();
                task.Busy = true;
            }
            Action<TaskDetail> wrapper = TaskWrapper;
            TaskDetail detail = new TaskDetail()
            {
                Name = name,
                Wrapper = wrapper,
                Action = task.Action,
                Globls = task.Globls,
                State = state,
                Callback = callback
            };
            wrapper.BeginInvoke(detail, TaskCallback, detail);
        }

        private class TaskDetail
        {
            public string Name { get; set; }
            public Action<TaskDetail> Wrapper { get; set; }
            public TaskDelegate Action { get; set; }
            public object Globls { get; set; }
            public object State { get; set; }
            public object ReturnValue { get; set; }
            public Exception Exception { get; set; }
            public TaskCallback Callback { get; set; }
        }

        private static void TaskWrapper(TaskDetail task)
        {
            try
            {
                task.ReturnValue = task.Action.Invoke(task.Globls, task.State);
            }
            catch (Exception e)
            {
                task.Exception = e;
            }
        }
        
        private void TaskCallback(IAsyncResult ar)
        {
            var detail = (TaskDetail)ar.AsyncState;
            detail.Wrapper.EndInvoke(ar);
            lock (tasks)
            {
                tasks[detail.Name].Busy = false;
            }
            try
            {
                if (detail.Callback != null)
                    detail.Callback.Invoke(detail.ReturnValue, detail.Exception);
            }
            catch (Exception)
            {
                //throw;
            }
        }
    }

#endif
}
